using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace GPSCore.NMEA.COMSource
{
    /// <summary>
    /// Rappresent a COM Port Configuration object
    /// </summary>
    public class COMConfiguration
    {
        #region members

        private string m_portName;
        private int m_baudRate;
        private System.IO.Ports.Parity m_parity;
        private int m_dataBits;
        private System.IO.Ports.StopBits m_stopBits;

        #endregion

        #region Constructors
        
        /// <summary>
        /// Rappresent a COM Port Configuration object
        /// </summary>
        public COMConfiguration()
        {
            //by default set this values:
            m_parity = System.IO.Ports.Parity.None;
            m_dataBits = 8;
            m_stopBits = System.IO.Ports.StopBits.One;
        }

        /// <summary>
        /// Rappresent a COM Port Configuration object
        /// </summary>
        /// <param name="portName"></param>
        /// <param name="baudRate"></param>
        /// <param name="parity"></param>
        /// <param name="dataBits"></param>
        /// <param name="stopBits"></param>
        public COMConfiguration(string portName, int baudRate, System.IO.Ports.Parity parity, int dataBits, System.IO.Ports.StopBits stopBits)
        {
            m_portName = portName;
            m_baudRate = baudRate;
            m_parity = parity;
            m_dataBits = dataBits;
            m_stopBits = stopBits;
        }

        #endregion

        #region properties

        /// <summary>
        /// PortName.
        /// 
        /// COM1, COM2, COM3 ecc ecc
        /// </summary>
        public string PortName
        {
            get { return m_portName; }
            set { m_portName = value; }
        }

        /// <summary>
        /// BaudRate
        /// 
        /// 1200, 2400 ecc ecc
        /// </summary>
        public int BaudRate
        {
            get { return m_baudRate; }
            set { m_baudRate = value; }
        }

        /// <summary>
        /// Parity
        /// </summary>
        public System.IO.Ports.Parity Parity
        {
            get { return m_parity; }
            set { m_parity = value; }
        }

        /// <summary>
        /// DataBits
        /// 
        /// Tipically 8 
        /// </summary>
        public int DataBits
        {
            get { return m_dataBits; }
            set { m_dataBits = value; }
        }

        /// <summary>
        /// StopBits
        /// 
        /// Tipically 1
        /// </summary>
        public System.IO.Ports.StopBits StopBits
        {
            get { return m_stopBits; }
            set { m_stopBits = value; }
        }

        #endregion

        #region members

        /// <summary>
        /// Deserialize a COMConfiguration from XmlDocument
        /// </summary>
        /// <param name="ConfigurationXml"></param>
        public static COMConfiguration COMConfigurationFromXmlDocument(XmlDocument ConfigurationXml)
        {
            XmlSerializer _xmlSer = new XmlSerializer(typeof(COMConfiguration));

            XmlTextReader _xmlReader = new XmlTextReader(new StringReader(ConfigurationXml.OuterXml));

            if (_xmlSer.CanDeserialize(_xmlReader))
            {
                return (COMConfiguration) _xmlSer.Deserialize(_xmlReader);
            }
            else
            {
                throw new Exception("Impossible to Deserialize the COMPort Configuration Xml");
            }
        }

        /// <summary>
        /// Rappresent a COM Port Configuration object 
        /// 
        /// Builded from a path of an Xml
        /// </summary>
        /// <param name="ConfigurationXmlFilePath"></param>
        public static COMConfiguration COMConfigurationFromXmlDocument(string ConfigurationXmlFilePath)
        {
            XmlDocument _xmlDoc = new XmlDocument();

            try
            {
                _xmlDoc.Load(ConfigurationXmlFilePath);
            }
            catch
            {
                throw new Exception("Invalid Xml Format for COMPort Configuration Xml");
            }

            return COMConfigurationFromXmlDocument(_xmlDoc);
        }

        /// <summary>
        /// Serialize a COMConfiguration to a XmlDocument
        /// </summary>
        /// <returns></returns>
        public XmlDocument ToXml()
        {
            XmlSerializer _xmlSer = new XmlSerializer(typeof(COMConfiguration));
            MemoryStream _stream = new MemoryStream();
            XmlTextWriter _xmlWriter = new XmlTextWriter(_stream, Encoding.ASCII);

            try
            {
                _xmlSer.Serialize(_xmlWriter,this);
            }
            catch(Exception ex)
            {
              throw new Exception( "Impossible to Serialize COMConfiguration", ex);
            }

            XmlDocument _xmlDoc = new XmlDocument();
            _xmlDoc.Load(_stream);

            return _xmlDoc;
        }

        /// <summary>
        /// Configure a Serial Port to that configuration
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="serialPort"></param>
        public static void ConfigureSerialPort(COMConfiguration configuration, System.IO.Ports.SerialPort Port)
        {
            if (Port == null)
            {
                Port = new System.IO.Ports.SerialPort(configuration.PortName, configuration.BaudRate, configuration.Parity, configuration.DataBits, configuration.StopBits);
            }
            else
            {
                Port.PortName = configuration.PortName;
                Port.BaudRate = configuration.BaudRate;
                Port.Parity = configuration.Parity;
                Port.DataBits = configuration.DataBits;
                Port.StopBits = configuration.StopBits;
            }
        }

        #endregion

    }
}
